package cn.shen.sheng.da.service.impl;

import cn.shen.sheng.da.common.ServerResponse;
import cn.shen.sheng.da.manager.CourseDao;
import cn.shen.sheng.da.mapper.*;
import cn.shen.sheng.da.model.entity.ClassEntity;
import cn.shen.sheng.da.model.entity.CourseEntity;
import cn.shen.sheng.da.model.entity.HolidayVo;
import cn.shen.sheng.da.model.vo.request.ConstantInfo;
import cn.shen.sheng.da.model.vo.response.CourseInfoVO;
import cn.shen.sheng.da.model.vo.response.TeacherVO;
import cn.shen.sheng.da.service.ClassTaskService;
import cn.shen.sheng.da.util.ClassUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author lequal
 * @since 2020-04-06
 */
@Service
@Slf4j
public class ClassTaskServiceImpl  implements ClassTaskService {

    @Autowired
    private ClassMapper classTaskDao;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private HolidayVoMapper holiday;
    @Autowired
    private CourseDao courseDao;
    @Autowired
    private CoursePlanMapper coursePlanMapper;


    // 不固定上课时间 1
    private final String UNFIXED_TIME = "unFixedTime";

    // 固定上课时间 2
    private final String IS_FIX_TIME = "isFixedTime";



    /**
     * 排课算法入口
     * @param
     * @return
     */
    @Transactional
    public ServerResponse classScheduling(String term, List<String> classDates) {
        // 创建一个列表来存储修改后的课程实例
        /*List<CourseInfoVO> modifiedCourseList = new ArrayList<>();*/
        long start = 0;
        try {
            log.info("开始排课,时间：" + System.currentTimeMillis());
            start = System.currentTimeMillis();

            QueryWrapper<CourseEntity> wrapper = new QueryWrapper<CourseEntity>().eq("term", term).orderByAsc("course_order");

            List<CourseEntity> classTaskList = courseMapper.selectList(wrapper);
            System.out.println("排序后班级信息 ================================================ " + classTaskList);

            if (classTaskList == null) {
                return ServerResponse.ofError("排课失败，查询不到排课任务！");
            }
            int courseCount = courseMapper.count1(term);
            /*System.out.println("courseList = " + classTaskList);*/
            List<HolidayVo> holidayVos = null;
            for (String date : classDates) {
                // 你可以根据需要处理日期，例如将字符串转换为日期对象
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate startDate = LocalDate.parse(date, formatter);
                holidayVos = holiday.allHoliday1(startDate);
            }
            // 2、将开课任务的各项信息进行编码成染色体，分为固定时间与不固定时间
            List<Map<String, List<String>>> geneList = null;
            if (holidayVos != null) {
                geneList = coding(courseCount,classTaskList, holidayVos);
            }
            else {
                log.info("假期为空");
            }
            /*System.out.println("geneList = " + geneList);*/

            // 3、给初始基因编码随机分配时间，得到同班上课时间不冲突的编码
            List<String> resultGeneList = null;
            if (geneList != null) {
                resultGeneList = codingTime(classTaskList,geneList, holidayVos);
            }
            else {
                log.info("分配时间为空");
            }
            System.out.println(" 分配时间后resultGeneList = " + resultGeneList.size());
            // 4、将分配好时间的基因编码以班级分类成为以班级的个体，得到班级的不冲突时间初始编码
            System.out.println("初始化调用开始--------------------------------------------");
            Map<String, List<String>> individualMap = null;
            individualMap = transformIndividual(resultGeneList);
            System.out.println("初始化调用结束 -------------------------------------------" );
            // 5、遗传进化
            individualMap = geneticEvolution(courseCount,individualMap);
            // 6、分配教室并做教室冲突检测
            List<String> resultList = finalResult(individualMap);
            /*System.out.println("确认信息 = " + resultList);*/
            // 7、解码最终的染色体获取其中的基因信息
            List<CourseInfoVO> coursePlanList = decoding(resultList);
            // 8、写入tb_course_plan上课计划表
            scheduleMapper.deleteSchedule(); // 先删除原来的课程计划
            for (CourseInfoVO coursePlan : coursePlanList) {
               /* System.out.println("coursePlan = " + coursePlan);*/
                scheduleMapper.insertCoursePlan(coursePlan.getClassId(), String.valueOf(coursePlan.getCourseId()), coursePlan.getClassTime(),
                        coursePlan.getTeacherNumber(), coursePlan.getStartDate(), coursePlan.getEndDate(), coursePlan.getClassWeeks(), coursePlan.getIsCompleted(),coursePlan.getRoom());
                /*System.out.println("解码教师号"+coursePlan.getTeacherNumber());*/
            }
            log.info("完成排课,耗时：" + (System.currentTimeMillis() - start));
            return ServerResponse.ofSuccess("排课成功！");
        } catch (Exception e) {
            log.error("the error message is:" + "    " + e.getMessage());
            e.printStackTrace();
            return ServerResponse.ofError("排课失败，出现异常!");
        }
    }
    private TeacherVO getRandomTeacher(List<TeacherVO> teachers) {
        if (teachers.isEmpty()) {
                return null;
        }

        Random random = new Random();
        int randomIndex = random.nextInt(teachers.size());

        return teachers.get(randomIndex);


    }

    /**
     * 给进化完的基因编码分配班级，即在原来的编码中加上班级编号
     * @param individualMap
     * @return
     */
    private List<String> finalResult(Map<String, List<String>> individualMap) {
        List<String> resultList = new ArrayList<>();
        /*System.out.println("所有基因不带教室编码=========================："+individualMap);*/
        List<String> resultGeneList = collectGene(individualMap);
        /*System.out.println("所有基因不带教室编码=========================："+resultGeneList);*/
        List<ClassEntity> classroomList = classTaskDao.allClasses();


        List<String> classIdList = classTaskDao.selectByColumnName(ConstantInfo.CLASS_ID);
        /*System.out.println("班级id================================"+classIdList);*/
        System.out.println("分配教室是前基因数量====--=--=="+resultGeneList.size());
        System.out.println("----------------------开始分配教室---------------");
        for (String gene : resultGeneList) {
            //拿到的基因编码
           /* System.out.println("拿到的基因编码 = " + gene);*/
            String combinedGene; // 使用原始的基因进行初始化
            String classId = gene.substring(1,9);
            ClassEntity classEntity = classTaskDao.allClassesById(Integer.valueOf(classId));
            if (classEntity != null) {
                    String classroom = classEntity.getRoom();

                    combinedGene = gene.substring(0,26) + classroom+gene.substring(32);
                    /*System.out.println("带教室基因编码= --------------"+combinedGene);*/

                        resultList.add(combinedGene);
                        //break; // 一旦安排，跳出此基因的循环。


            }
        }
        System.out.println("分配完教室后基因数量"+resultList.size()+"====="+resultList);

        return resultList;
    }
    public static String replaceGene1To8(String gene, String newPart) {
        if (gene.length() < 9) {
            // 基因长度不足9位，无法替换
            return newPart + gene.substring(Math.min(8, gene.length())); // 将新值添加到原始基因的后面
        }

        String updatedGene = gene.substring(0, 1) + newPart + gene.substring(9); // 保留索引0上的数据，将1-8位替换为新的值

        return updatedGene;
    }

    private List<String> extractClassIdsFromGene(String gene) {
        List<String> classIds = new ArrayList<>();
        // 使用 ClassUtil.cutGene 方法从基因中提取班级ID
        String classId = ClassUtil.cutGene(ConstantInfo.CLASS_ID, gene);

        // 添加提取的班级ID到列表
        if (!classId.isEmpty()) {
            classIds.add(classId);
        }
        System.out.println("classIds==============="+classIds);

        return classIds;

        // 实现代码逻辑以从基因中提取班级ID。
        // 具体提取逻辑取决于基因的实际结构。
        // 例如，如果班级ID由下划线分隔，可以使用字符串分割方法来提取。


    }



    /*
    用班级id找到对应的班级实体类，找出对应教室
    * @Param classId
    * @return ClassEntity
    * */



    private ClassEntity findClassroomByClassID(List<ClassEntity> classroomList, Integer classID) {
        for (ClassEntity classroom : classroomList) {
            if (classroom.getClassId().equals(classID)) {
                return classroom;
            }
        }

        return null;
    }




    /**
     * 判断教室是否符合上课班级所需
     * @param classroom 教室
     * @param resultList
     * @return
     */
    private Boolean judgeClassroom(String gene,ClassEntity classroom, List<String> resultList) {
        // 判断教室是否空闲
        return isFree(gene,resultList, classroom);
    }


    /**
     * 判断同一时间同一个教室是否有多个班级使用
     * @param gene
     * @param resultList
     * @param classroom
     * @return
     */
    private Boolean isFree(String gene, List<String> resultList, ClassEntity classroom) {
        // 如果resultList为空说明还没有教室被分配,直接返回true
        if (resultList.size() == 0) {
            return true;
        } else {
            for (String resultGene : resultList) {
                // 如果当前教室在之前分配了则需要去判断时间是否有冲突
                if (ClassUtil.cutGene(ConstantInfo.ROOM, resultGene).equals(classroom.getRoom())) {
                    // 判断时间是否一样，一样则表示有冲突
                    if (ClassUtil.cutGene(ConstantInfo.CLASS_TIME, gene).equals(ClassUtil.cutGene(ConstantInfo.CLASS_TIME, resultGene))) {
                        return false;
                    }
                }
            }
        }
        return true;
    }


    /**
     * 对所有的基因编码进行处理，不再按年级分类
     * @param resultGeneList
     * @return
     */
    private List<String> collectAllGenes(List<String> resultGeneList) {
        // 直接返回所有的基因编码
        return resultGeneList;
    }


    /**
     * 遗传进化(每个班级中多条基因编码)
     * 步骤：
     * 1、初始化种群
     * 2、交叉，选择
     * 3、变异
     * 4、重复2,3步骤
     * 5、直到达到终止条件
     *
     * @param courseCount
     * @param individualMap 按班级分的基因编码
     * @return
     */
    private Map<String, List<String>> geneticEvolution(int courseCount, Map<String, List<String>> individualMap) {
        // 遗传代数
        int generation = ConstantInfo.GENERATION;
        List<String> resultGeneList;
        for (int i = 0; i < generation; ++i) {
            // 1、选择、交叉individualMap：按班级分的课表
            individualMap = hybridization(individualMap);
            // 2、合拢所有班级的个体
            collectGene(individualMap);
            // 2,3、变异
            resultGeneList = geneMutation(collectGene(individualMap));
            // 4、冲突检测，消除冲突
            /*conflictResolution(resultGeneList);*/
            // 5、将消除冲突后的个体再分班进入下一次进化
            if (courseCount > 30){
                System.out.println("调用冲突解决方法1-----------------------------------------");
                individualMap = transformIndividual(conflictResolution2(resultGeneList));
            }
            else {
                System.out.println("调用冲突解决方法2-----------------------------------------");
                individualMap = transformIndividual(conflictResolution(resultGeneList));
            }

        }
        return individualMap;
    }



    /**
     * 冲突消除,同一个讲师同一时间上多门课。解决：重新分配一个时间，直到所有的基因编码中
     * 不再存在上课时间冲突为止
     * 因素：讲师-课程-时间-教室
     * @param resultGeneList 所有个体集合
     * @return
     */
    private List<String> conflictResolution(List<String> resultGeneList) {
        int conflictTimes = 0;
        eitx:
        for (int i = 0; i < resultGeneList.size(); i++) {
            // 得到集合中每一条基因编码的编码信息
            String gene = resultGeneList.get(i);
            String teacherNo = ClassUtil.cutGene(ConstantInfo.TEACHER_NUMBER, gene);
            String classTime = ClassUtil.cutGene(ConstantInfo.CLASS_TIME+ConstantInfo.DATE, gene);
            String classNo = ClassUtil.cutGene(ConstantInfo.CLASS_ID, gene);
            for (int j = i + 1; j < resultGeneList.size(); j++) {
                // 再找剩余的基因编码对比
                String tempGene = resultGeneList.get(j);
                String tempTeacherNo = ClassUtil.cutGene(ConstantInfo.TEACHER_NUMBER, tempGene);
                String tempClassTime = ClassUtil.cutGene(ConstantInfo.CLASS_TIME+ConstantInfo.DATE, tempGene);
                String tempClassNo = ClassUtil.cutGene(ConstantInfo.CLASS_ID, tempGene);
                // 判断是否有同一讲师同一时间上两门课

                // 冲突检测
                if (classTime.equals(tempClassTime)) {
                    if (classNo.equals(tempClassNo) || teacherNo.equals(tempTeacherNo)) {
                        System.out.println("出现冲突情况");
                        conflictTimes ++;
                        String newClassTime = ClassUtil.randomTime(gene, resultGeneList);
                        String newGene = gene.substring(0, 24) + newClassTime+gene.substring(26);

                        resultGeneList = replace(resultGeneList, gene, newGene);

                        /*i = -1;*/

                        continue eitx;

                    }

                }

            }
        }
        System.out.println("冲突发生次数:" + conflictTimes);
        return resultGeneList;
    }

    /**
     * 替换基因编码
     * @param resuleGeneList
     * @param oldGene
     * @param newGene
     * @return
     */
    private List<String> replace(List<String> resuleGeneList, String oldGene, String newGene) {
        for (int i = 0; i < resuleGeneList.size(); i++) {
            if (resuleGeneList.get(i).equals(oldGene)) {
                resuleGeneList.set(i, newGene);
                System.out.println("执行替换方法");
                return resuleGeneList;
            }
        }
        return resuleGeneList;
    }
    // 备用冲突解决

    /**
     * 发生错误地方：
     * 错误原因：基因部分缺损（分配时间和日期缺失）
     * 猜测原因：在解决时间冲突时，发生冲突，丢失基因未重新进行基因分配
     * 解决措施：1，尝试第一种解决冲突办法重新分配基因
     *         2.改进冲突二分配时间方法，并写出判断防止，出错后找不出错误具体位置
     *
     * @param resultGeneList
     * @return
     */
    List<String> conflictResolution2(List<String> resultGeneList) {
        int illGene = 0;
        int genes =0;
        System.out.println("执行备用的替换方法");
        System.out.println("开始基因检测修补queshi------------------------------------------------------");
        for (String s : resultGeneList ){
            if (s.length()<42){
                illGene++;
            }else {
                genes++;
            }
        }
        System.out.println("基因检测结束--------------------------------------------------------");
        System.out.println("合格基因数:"+genes+"\n不合格基因数："+illGene);
        Set<String> legalGeneSet = new HashSet<>();
        Set<String> illegalGeneSet = new HashSet<>();
        List<String> newResultGeneList = new ArrayList<>();
        //搜索冲突。
        resultGeneList.forEach(s -> {

            String teacherNumber = s.substring(9, 19);
            String classTime = s.substring(24, 26);
            String key = String.format("%s-%s", teacherNumber, classTime);
            //判断同一时间老师是否还在别的地方上课。
            if (!legalGeneSet.contains(key)) {
                legalGeneSet.add(key);
                newResultGeneList.add(s);
            } else {

                illegalGeneSet.add(s);
            }
        });
        //解决冲突。
        // 新增问题有一条基因缺少教室信息：120060141200200456110018102023-01-02
        illegalGeneSet.forEach(s -> {
            String isFix = s.substring(0, 1);
            /*String gradeNo = s.substring(1, 3);*/
            String classId = s.substring(1, 9);
            String teacherNumber = s.substring(9, 19);
            String courseId = s.substring(19, 24);
            /*String courseAttr = s.substring(22, 24);*/
            /*String room = s.substring(26, 32);*/
            int classTime = Integer.parseInt(s.substring(24, 26));
            String room = s.substring(26,32);
            String date = s.substring(32,42);
            //搜索一个合法时间并分配。
            for (int newClassTime = 1; newClassTime <= 20; newClassTime++) {
                if (newClassTime != classTime) {
                    String key = String.format("%s-%02d", teacherNumber, newClassTime);
                    if (!legalGeneSet.contains(key)) {
                        legalGeneSet.add(key);
                        String gene = String.format("%s%s%s%s%02d",
                                isFix, classId, teacherNumber,courseId,newClassTime,room,date);
                        newResultGeneList.add(gene);
                        break;
                    }
                }
            }
        });
        System.out.println("结局冲突后基因总数-------==-=-==-==---==-"+newResultGeneList);
        return newResultGeneList;
    }


    /**
     * 重新合拢交叉后的个体,即不分班级的基因编码，得到所有的编码
     * @param individualMap
     * @return
     */
    private List<String> collectGene(Map<String, List<String>> individualMap) {
        int gene2 = 0;
        int illGene2 = 0;


        List<String> resultList = new ArrayList<>();
        for (List<String> individualList : individualMap.values()) {

            for (int i = 0; i < individualList.size(); i++) {
                String genes = individualList.get(i);

                if (genes.length() < 42) {
                    // 如果当前基因长度小于 42，说明基因缺失

                    String room1 = ConstantInfo.DEFAULT_CLASS_ROOM;
                    String time1 = ClassUtil.randomTime(genes, individualList);
                    System.out.println("修补基因的得到的随机时间" + time1 + "默认教室" + room1);

                    String missingGenes = time1+room1;
                    // 用 room1 + time1 替代缺失的基因部分

                    String newGenes = genes.substring(0, 24) + missingGenes + genes.substring(24);
                    // 在第24位处插入缺失的基因
                    System.out.println("原来基因"+genes+"\n修复基因"+newGenes);
                    illGene2++;


                    individualList.set(i, newGenes);
                    // 更新列表中的基因
                }else {
                    gene2++;
                }
            }

            System.out.println("xv xfbhfdhtdgdsgth------------------------"+individualList.size());
            System.out.println("重新合拢交叉后的个体合格基因数："+gene2+"" +
                    "不合格基因数"+illGene2);

            resultList.addAll(individualList);
        }
        System.out.println("交叉后收拢基因总数"+resultList.size());

        return resultList;
    }

    /**
     * 基因变异
     * @param resultGeneList 所有的基因编码
     * @return
     */
    private List<String> geneMutation(List<String> resultGeneList) {
        int gene3 = 0;
        int illGene3 = 0;
        int gene4 = 0;
        int illGene4 = 0;
        for (String resGene : resultGeneList){
            if (resGene.length()<42){
                gene4++;
            }else {
                illGene4++;
            }
        }
        System.out.println("变异前合格基因总数===："+gene4+"不合格基因数："+illGene4);

        int min = 0;
        int max = resultGeneList.size() - 1;
        System.out.println("max = " + max);
        // 变异率，需要合理设置，太低则不容易进化得到最优解；太高则容易失去种群原来的优秀解
        double mutationRate = 0.005; //0.002  0.003  0.004  0.005尽量设置低一些，0.01可能都大了
        // 设定每一代中需要变异的基因个数，基因数*变异率
        int mutationNumber = (int)(resultGeneList.size() * mutationRate);

        if (mutationNumber < 1) {
            mutationNumber = 1;
        }

        for (int i = 0; i < mutationNumber; ) {

            int temp = min + (int)(Math.random() * (max + 1 - min));
            // 随机拿一条编码
            String gene = resultGeneList.get(temp);
            if (ClassUtil.cutGene(ConstantInfo.IS_FIX, gene).equals("2")) {
                break;
            } else {
                // 再随机给它一个上课时间
                String newClassTime = ClassUtil.randomTime(gene, resultGeneList);
                //问题所在？？？？？？？？？？？？？？？？？ gene = gene.substring(0, 24) + newClassTime+gene.substring(32);
                gene = gene.substring(0, 24) + newClassTime+gene.substring(26);
                System.out.println("变异后基因检查-------------------------"+gene);
                // 去掉原来的个体
                resultGeneList.remove(temp);
                // 原来位置上替换成新的个体
                resultGeneList.add(temp, gene);
                i = i + 1;
            }
        }
        for (String resGene : resultGeneList){
            if (resGene.length()<42){
                gene3++;
            }else {
                illGene3++;
            }
        }
        System.out.println("变异后合格基因总数："+illGene3+"不合格基因数："+gene3);
        return resultGeneList;
    }

    /**
     * 给每个班级交叉：一个班级看作一个种群
     * @param individualMap
     * @return
     */
    private Map<String, List<String>> hybridization(Map<String, List<String>> individualMap) {

        // 对每一个班级的基因编码片段进行交叉
        for (String classId : individualMap.keySet()) {
            // 得到每一个班级对应的基因编码
            List<String> individualList = individualMap.get(classId);
            // 保存上一代
            List<String> oldIndividualList = individualList;
            // 交叉生成新个体,得到新生代
            individualList = selectGene(individualList);
            System.out.println("父代基因数量"+oldIndividualList.size()+"子代优秀基因"+individualList.size());
            // 计算并对比子父代的适应度值，高的留下进行下一代遗传
            if (ClassUtil.calculatExpectedValue(individualList) >= ClassUtil.calculatExpectedValue(oldIndividualList)) {
                individualMap.put(classId, individualList);
            } else {
                individualMap.put(classId, oldIndividualList);
            }
        }
        System.out.println("交叉后基因总数"+individualMap);

        return individualMap;
    }


    /**
     * 个体中随机选择基因进行交叉(交换上课时间)
     * @return
     */
    private List<String> selectGene(List<String> individualList) {
        int min = 0;
        int max = individualList.size() - 1;
        boolean flag;
        do {
            // 从班级集合中随机选取两个坐标以便获得随机的两条基因编码
            int firstIndex = min + (int)(Math.random() * (max + 1 - min));
            int secondIndex = min + (int)(Math.random() * (max + 1 - min));
            // 获取随机基因编码
            String firstGene = individualList.get(firstIndex);
            String secondGene = individualList.get(secondIndex);
            if (firstIndex == secondIndex) {
                flag = false;
            } else if(ClassUtil.cutGene(ConstantInfo.IS_FIX, firstGene).equals("2") || ClassUtil.cutGene(ConstantInfo.IS_FIX, secondGene).equals("2")) {
                // 上课时间已经固定
                flag = false;
            } else {
                // 分别获取两条基因编码中的上课时间，开始交叉
                String firstClassTime = ClassUtil.cutGene(ConstantInfo.CLASS_TIME+ConstantInfo.DATE, firstGene);
                String secondClassTime = ClassUtil.cutGene(ConstantInfo.CLASS_TIME+ConstantInfo.DATE, secondGene);
                // 交换它们的上课时间
                firstGene = firstGene.substring(0, 24) + secondClassTime+firstGene.substring(32);
                secondGene = secondGene.substring(0, 24) + firstClassTime+secondGene.substring(32);
                // 将新得到的两条基因编码替换原来班级中的基因编码
                individualList.remove(firstIndex);
                individualList.add(firstIndex, firstGene);
                individualList.remove(secondIndex);
                individualList.add(secondIndex, secondGene);
                flag = true;
            }
        } while (!flag);
        System.out.println("进化过程交叉后基因总数"+individualList.size());
        return individualList;
    }


   /* *//**
     * 编码规则:
     *  固定时间：1
     * 	年级编号：2
     * 	班级编号：8
     * 	讲师编号：5
     * 	课程编号：6
     * 	课程属性：2
     * 	上课时间：2
     * 	教室编号：6
     *
     * 编码规则为：是否固定+年级编号+班级编号+教师编号+课程编号+课程属性+上课时间
     * 其中如果不固定开课时间默认填充为"00"
     * 经过处理后得到开课任务中
     * @param classTaskList
     * @return List<String>
     *//*

    }*/
    /**
     * 根据课程信息生成基因编码，只考虑 `holiday` 表中 `status` 为 0 的日期
     *
     * @param
     * @param
     * @param courseCount
     * @param holidayVos
     * @return List<String>
     */

    private List<Map<String, List<String>>> coding(int courseCount, List<CourseEntity> classTaskList, List<HolidayVo> holidayVos) {
        List<Map<String, List<String>>> geneList = new ArrayList<>();
        Map<String, List<String>> geneListMap = new HashMap<>();
        List<CourseInfoVO> modifiedCourseList = new ArrayList<>();
        String holidayVo = holidayVos.get(0).getDate();
        /*System.out.println("----------------------------------------------------------");*/
        /*System.out.println("未知====== = " + holidayVo);*/


        List<String> unFixedTimeGeneList = new ArrayList<>();
        Integer classCount = classTaskDao.count();
        int classCount1 = 1;
        int sumWeek;

        List<ClassEntity> classEntities = classTaskDao.allClasses();
        for (ClassEntity classId : classEntities){

                for (CourseEntity course : classTaskList) {
                    CourseInfoVO modifiedCourse = new CourseInfoVO(); // 为每门课程创建一个新实例

                    modifiedCourse.setCourseId(course.getCourseId());
                    modifiedCourse.setCourseName(course.getCourseName());
                    modifiedCourse.setHours(course.getHours());
                    modifiedCourse.setCourseStatus(course.getCourseStatus());
                    modifiedCourse.setCourseOrder(course.getCourseOrder());
                    modifiedCourse.setCourseLevel(course.getCourseLevel());
                    modifiedCourse.setTerm(course.getTerm());
                    modifiedCourse.setIsFax(course.getIsFax());
                    String courseName = course.getCourseName();
                  /*  System.out.println("courseName = " + courseName);*/
                    List<TeacherVO> teachersByCourseName = courseDao.getTeachersByCourseName(courseName);
                    TeacherVO teacher = getRandomTeacher(teachersByCourseName);
                    if (teacher != null) {
                        modifiedCourse.setTeacherName(teacher.getTeacherName());
                        modifiedCourse.setTeacherId(teacher.getTeacherId());
                        modifiedCourse.setTeacherLevel(teacher.getTeacherLevel());
                        modifiedCourse.setTeacherAbility(teacher.getTeacherAbility());
                        modifiedCourse.setTeacherNumber(teacher.getTeacherNumber());
                    }

                   /* System.out.println("classCount1========================"+classCount1);
                    System.out.println("classCount========================"+classCount);
                    System.out.println("courseCount======================"+courseCount);*/
                    modifiedCourse.setClassId(String.valueOf(classId.getClassId()));
                    // 将修改后的课程实例添加到列表中
                    modifiedCourseList.add(modifiedCourse);
                    //System.out.println("未编码课程信息=============================" + modifiedCourseList);
            }
        }
        System.out.println("初始添加总数======================="+ (long) modifiedCourseList.size());
            for (CourseInfoVO course : modifiedCourseList) {
                // 获取课程的总课时数量
                int totalCourseHours = course.getHours();
               /* System.out.println("totalCourseHours = " + totalCourseHours);*/
                Random random =new Random();
                if(courseCount==1){
                    sumWeek = random.nextInt(2)+15;
                }
                else {
                     sumWeek = random.nextInt(2) + 8;
                }

                // 计算这门课总上课节数
                int totalClassesPerWeek = (int) (totalCourseHours / 1.5); // 假设每节课1.5学时
                double weeks = totalClassesPerWeek / sumWeek;
                //上课周数
                int week = (int) Math.ceil(weeks)+1;
                System.out.println("要上===== " + week+"=====周课");

                course.setClassWeeks(String.valueOf(week));
               /* System.out.println("week = " + week);*/
                    for (int i = 0; i < totalClassesPerWeek; i++) {
                        String gene = course.getIsFax()  + course.getClassId()
                                + course.getTeacherNumber() + course.getCourseId()  + ConstantInfo.DEFAULT_CLASS_TIME+ConstantInfo.DEFAULT_CLASS_ROOM;
                        unFixedTimeGeneList.add(gene);
                        if (gene.length() <32){
                            System.out.println("此基因编码出错"+gene);
                        }
                    }
                System.out.println("编码总数+==============="+unFixedTimeGeneList.size());
            }
        /*System.out.println("unFixedTimeGeneList=="+unFixedTimeGeneList);*/
        geneListMap.put(UNFIXED_TIME, unFixedTimeGeneList);

        geneList.add(geneListMap);
        // 得到不含教室的初始基因编码
        return geneList;
    }


    /**
     * 给初始基因编码随机分配时间(那些不固定上课时间的课程)
     *
     * @param classTaskList
     * @param geneList      固定时间与不固定时间的编码集合
     * @param holidayVos
     * @return
     */
    private List<String> codingTime(List<CourseEntity> classTaskList, List<Map<String, List<String>>> geneList, List<HolidayVo> holidayVos) {
        List<String> resultGeneList = new ArrayList<>();
        /*List<String> isFixedTimeGeneList = geneList.get(0).get(IS_FIX_TIME);*/
        List<String> unFixedTimeGeneList = geneList.get(0).get(UNFIXED_TIME);
        System.out.println("给初始基因编码随机分配时间geneList = " + geneList);
        int dayGroupIndex = 0;
        int illGeneByTime = 0;

        int illGeneByTime1 = 0;
        int geneByTime = 0;
        int geneByTime1 = 0;

// 定义日期组列表
        List<List<Integer>> dayGroups = new ArrayList<>();
        for (int j = 1; j <= 5; j++) {
            List<Integer> group = new ArrayList<>();
            for (int k = j * 4 - 3; k <= j * 4; k++) {
                group.add(k);
            }
            dayGroups.add(group);
        }

// 循环处理没有固定时间的课程
        for (String gene : unFixedTimeGeneList) {
            if (gene.length()<32){
                illGeneByTime++;
            }
            else {
                geneByTime++;
            }
            // 获取当前日期组的第一个日期
            String currentDate = holidayVos.get(dayGroupIndex * 5).getDate();

            // 获取当前日期所属的日期组
            List<Integer> dayGroup = dayGroups.get(dayGroupIndex);
            // 生成随机时间
            String classTime = ClassUtil.randomTime(gene, resultGeneList);
            // 将随机时间与日期组合并
            gene = gene.substring(0,24) + classTime+gene.substring(26,32)+currentDate;
            if (gene.length()<42){
                System.err.println(" 分配完时间后Error: Gene length is less than 32 characters.");
            }
            if (gene.length()<42){
                illGeneByTime1++;
            }
            else {
                geneByTime1++;
            }

            // 添加到基因编码列表
            resultGeneList.add(gene);
            // 更新日期组索引以处理下一个日期组
            dayGroupIndex = (dayGroupIndex + 1) % dayGroups.size();
        }
        System.out.println("在分配时间时合格基因数"+geneByTime+"\n 不合格基因数"+illGeneByTime);
        System.out.println("在分配时间之后合格基因数"+geneByTime1+"\n 不合格基因数"+illGeneByTime1+"\n"+resultGeneList);

        // 这个集合只是同一个班级内上课时间不冲突的
        return resultGeneList;
    }

    /**
     * 将初始基因编码(都分配好时间)划分以班级为单位的个体
     * 班级编号的集合，去重
     * @param resultGeneList
     * @return
     */
    private Map<String, List<String>> transformIndividual(List<String> resultGeneList) {
        Map<String, List<String>> individualMap = new HashMap<>();
        // 查询开课的班级
        List<String> classNoList = classTaskDao.selectClassNo();
        int gene1 = 0;
        int illGene1 = 0;
        String gene4 = null;
        System.out.println("初始基因编码前"+resultGeneList.size());
        /*for (String classNo : classNoList) {*/
        List<String> geneList = new ArrayList<>();
        for (String gene : resultGeneList) {
            if (gene.length()<42){
                illGene1++;
                System.out.println("不合格以班级id为键值对时检测"+gene);
            }
            else {
                gene1++;
            }                 // 把含有该班级编号的基因编码加入集合
            gene4=gene.substring(1,9);
            geneList.add(gene);
            if (geneList.size() > 0) {
                individualMap.put(gene4, geneList);
            }
        }
        System.out.println("以班级id为键值对时检测合格基因数:"+gene1+"\n 不合格基因数:"+illGene1);
        /*System.out.println("geneList = " + geneList);*/
        // 根据班级分配基因编码集合>1
        /*}*/
        System.out.println("简直队形基因"+individualMap);
        // 得到不同班级的初始课表
        return individualMap;

    }



    /**
     * 解码染色体中的基因，按照之前的编码解
     * 编码:
     * 固定时间：1
     * 班级编号：8
     * 讲师编号：10
     * 课程编号：5
     * 上课时间：2
     * 教室编号：6
     * 编码规则为：是否固定+班级编号+教师编号+课程编号+上课时间+教室编号(遗传算法执行完最后再分配教室)
     * 其中如果不固定开课时间默认填充为"00"
     *
     * @param resultList 全部上课计划实体
     * @return
     */
    private List<CourseInfoVO> decoding(List<String> resultList) {
        List<CourseInfoVO> coursePlanList = new ArrayList<>();
        for (String gene : resultList) {
            CourseInfoVO coursePlan = new CourseInfoVO();
            // 班级
            coursePlan.setClassId(String.valueOf(Integer.valueOf(ClassUtil.cutGene(ConstantInfo.CLASS_ID, gene))));
            // 课程
            coursePlan.setCourseId(Integer.valueOf(String.valueOf(Integer.valueOf(ClassUtil.cutGene(ConstantInfo.COURSE_ID, gene)))));
            // 讲师
            coursePlan.setTeacherNumber(Integer.valueOf(ClassUtil.cutGene(ConstantInfo.TEACHER_NUMBER, gene)));
            // 教室
            coursePlan.setRoom(ClassUtil.cutGene(ConstantInfo.ROOM, gene));
            coursePlan.setStartDate(LocalDate.parse(ClassUtil.cutGene(ConstantInfo.DATE,gene)));
            // 上课时间
            coursePlan.setClassTime(ClassUtil.cutGene(ConstantInfo.CLASS_TIME, gene));
            coursePlanList.add(coursePlan);
        }
        return coursePlanList;
    }
}
